package 编程模式;

import java.util.concurrent.*;

/**
 * 创建线程有四种方式，分别是：
 * 1. 继承 thread 类，重写 thread 类的 run() 方法；
 * 2. 实现 runnable 借口，实现 run() 方法；
 * 3. 实现 callable 接口，实现 call() 方法；再调用 future task 类接收 call 的执行结果；
 * 4. 利用 executor 线程池来生产线程；
 *
 * //==============
 * 有个小 bug ，在运行 funtools.main 方法后，进程无法停止，原因是，线程池存在最小存活线程数量；
 */
public class MyThread {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 第一种：继承 thread 类
        ThreadImpl t1 = new ThreadImpl();
        t1.start();
        // 第二种：实现 runnable 接口
        Thread t2 = new Thread(new ThreadRun());
        t2.start();
        // 第三种:实现 callable 接口
        FutureTask<String> futureTask = new FutureTask<>(new ThreadCall());
        Thread t3 = new Thread(futureTask);
        t3.start();
        System.out.println(futureTask.get()); // 这是一个闭锁，在 t3.start() 线程体还饿米有执行完时，则无法获取结果
        // 第四种：线程池
        Executors executors = new Executors();
        executors.execute(new ThreadRun()); // 这个没办法赋予其名称了
    }
}

// 第一种，最简单，也最不推荐
class ThreadImpl extends Thread {
    public void run() {
        System.out.println("this is thread implement class!!!");
    }
}

// 第二种，推荐，原因，体量小且可以不丢失类的继承性
class ThreadRun implements Runnable {
    @Override
    public void run() {
        System.out.println("this is runnable implement class!!!");
    }
}

// 第三种：泛型代表返回类型的值
class ThreadCall implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "this is callable implement class !!!";
    }
}

// 第四种：利用 executor 来创建线程池，然后利用线程池来生产线程去执行
class Executors extends ThreadPoolExecutor {

    /**
     * 线程池的工作机制：
     *    1. 如果新来任务时，池内线程少于 core pool size 大小，则新建线程；
     *    2. 若是当前线程数量大于或者等于 core pool size 大小，则线程任务入队
     *    3. 若是当前池内线程已经达到最大，则直接把任务入队
     *
     * @param corePoolSize    核心线程数
     * @param maximumPoolSize 最大线程数
     * @param keepAliveTime   活跃线程数
     * @param unit            时间单位
     * @param workQueue       存储现成的队列
     */
    public Executors(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    public Executors() {
        super(5, 20,2l, TimeUnit.MILLISECONDS, (BlockingQueue)new LinkedBlockingQueue<>());
    }

    @Override
    public void execute(Runnable command) {
        System.out.println("this is thread pool class!!!");
        super.execute(command);
    }
}
